package com.xjrh.traintravel.collector.netty.coder;

import com.xjrh.traintravel.collector.netty.coder.command.AgreementStructure;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;

/**
 * 解码器
 * @author snps
 * @create 2022-01-18 10:16
 * @describe
 **/
@Slf4j
public class Decoder {

    private static final String START = "start";
    private static final String END = "end";

    /**
     * 解码
     * @param msg 接收到的16进制数据
     * @return 解码后的协议
     */
    public static AgreementStructure decode(Object msg) {
        if (msg == null) {
            log.error("服务端收到的消息为空!");
            return null;
        }

        // 进行消息解析
        String message = msg.toString();

        AgreementStructure agreement = new AgreementStructure();
        agreement.setPc(message.substring(0, 8));
        agreement.setSd(message.substring(8, 10));
        agreement.setFc(message.substring(10, 12));
        agreement.setAddr(message.substring(12, 24));
        agreement.setSeq(message.substring(24, 26));
        agreement.setLen(message.substring(26, 30));
        // 因"长度"为可变值，所以从长度位置后需要进行"数据起始位置和结束位置的计算"
        int startIndex = 30 ;
        int endIndex = startIndex + (Integer.parseUnsignedInt(agreement.getLen(), 16) * 2);
        agreement.setData(message.substring(startIndex, endIndex));
        // 设置"数据"后面的信息(校验、帧尾）
        Map<String, Integer> mapSubIndex = new HashMap();
        mapSubIndex = changeDataIndex(startIndex, endIndex, 4);
        agreement.setFcs(message.substring(mapSubIndex.get(START), mapSubIndex.get(END)));
        mapSubIndex = changeDataIndex(mapSubIndex.get(START), mapSubIndex.get(END), 2);
        agreement.setFs(message.substring(mapSubIndex.get(START), mapSubIndex.get(END)));

        return agreement;
    }

    /**
     * 改变数据区域的起始位置和结束位置
     * @param startIndex 起始位置
     * @param endIndex 结束位置
     * @param length 结束位置需要增加的长度
     */
    private static Map<String, Integer> changeDataIndex(int startIndex, int endIndex, int length) {
        Map<String, Integer> map = new HashMap();
        map.put("start", endIndex);
        map.put("end", endIndex + length);
        return map;
    }

}